// 面向过程

// 操作 -> 单元素 => 直接操作
// var title = document.getElementById("title");
// console.log(title.innerHTML);
// title.innerHTML = "标题";

// 操作 -> 多元素 => 遍历获取 在操作
// var liList = document.querySelectorAll(".list li");
// for (var i = 0; i < liList.length; i++) {
//     var li = liList[i];
//     li.innerHTML = "123123";
// }

// => 批量操作元素 => 有可能是单元素,多元素  => 方法有区别
// 使用 document.querySelectorAll()  无论是单元素获取还是多元素 => 都会存放到集合中

// debugger;
// 接收一个css选择器 作为参数
function GetEle (selector) {
  // {}
  // this -> {}

  this.eles = document.querySelectorAll(selector);
  // this.[[prototype]] = GetEle.prototype
  // return this;
}

// 获取和设置 集合中元素 html结构
// html("123123")   有参数就设置
// html()           没有参数就获取
GetEle.prototype.html = function (con) {
  // debugger;
  // this => 指向调用此方法的实例化对象 => 它也可以使用原型对象(prototypes)上的属性和方法 
  if (arguments.length >= 1) {  // 有参数就设置
    // for (var i = 0; i < this.eles.length; i++) {
    //     var ele = this.eles[i];
    //     ele.innerHTML = con;  // arguments[0]
    // }
    this.each(function (ele) {
      ele.innerHTML = con;
    })
    return this;
  } else {   //没有参数就获取
    return this.eles[0].innerHTML;
  }
}
// 获取和设置 集合中元素 text结构
// text("123123")   有参数就设置
// text()           没有参数就获取
GetEle.prototype.text = function (con) {
  if (arguments.length >= 1) {  // 有参数就设置
    // for (var i = 0; i < this.eles.length; i++) {
    //     var ele = this.eles[i];
    //     ele.innerText = con;  // arguments[0]
    // }
    this.each(function (ele) {
      ele.innerText = con;
    })
    return this;
  } else {   //没有参数就获取
    return this.eles[0].innerText;
  }
}

// 获取和设置 集合中表单元素 value值
// value("123123")   有参数就设置
// value()           没有参数就获取
GetEle.prototype.val = function (con) {
  if (arguments.length >= 1) {  // 有参数就设置
    // for (var i = 0; i < this.eles.length; i++) {
    //     var ele = this.eles[i];
    //     ele.value = con;  // arguments[0]
    // }
    this.each(function (ele) {
      ele.value = con;
    })
    return this;
  } else {   //没有参数就获取
    return this.eles[0].value;
  }
}

// 设置 集合中元素  隐藏
GetEle.prototype.hide = function () {
  // for (var i = 0; i < this.eles.length; i++) {
  //     var ele = this.eles[i];
  //     ele.style.display = "none";
  // }
  this.each(function (ele) {
    ele.style.display = "none";
  })
  return this;
}
GetEle.prototype.show = function () {
  // for (var i = 0; i < this.eles.length; i++) {
  //     var ele = this.eles[i];
  //     ele.style.display = "block";
  // }
  this.each(function (ele) {
    ele.style.display = "block";
  })
  return this;
}

GetEle.prototype.click = function (fn) {
  this.each(function (ele) {
    ele.onclick = fn;
  })
  return this;
}

GetEle.prototype.each = function (fn) {
  // this -> 调用此方法的实例化对象  {eles:[]}

  for (var i = 0; i < this.eles.length; i++) {
    var item = this.eles[i];
    var index = i;
    var array = this.eles;
    fn(item, index, array);

    // jquery中 它的each方法 参数顺序 fn(index, item);

  }
  return this;
}

// width() 获取和设置元素的宽度 
// width("100px")  有参数就设置
// width()         没有参数就获取

GetEle.prototype.width = function (con) {
  if (arguments.length >= 1) {
    this.each(function (ele) {

      // 是否有单位?
      //   有单位   px pt  %  em rem vw  vh   => 直接拼接
      // 没有单位   200                       => 默认"px"
      var unit = /^\d+(\.\d+)?(px|pt|%|em|rem|vw|vh)$/
      if (unit.test(con)) {
        ele.style.width = con;
      } else {
        ele.style.width = con + "px";
      }
    })
    return this;
  } else {
    // return this.eles[0].style.width;  // 只能获取内联样式
    // return parseInt(getStyle(this.eles[0], "width"));
    return parseInt(this.getStyle("width"));
  }
}

GetEle.prototype.height = function (con) {
  if (arguments.length >= 1) {
    this.each(function (ele) {

      // 是否有单位?
      //   有单位   px pt  %  em rem vw  vh   => 直接拼接
      // 没有单位   200                       => 默认"px"
      var unit = /^\d+(\.\d+)?(px|pt|%|em|rem|vw|vh)$/
      if (unit.test(con)) {
        ele.style.height = con;
      } else {
        ele.style.height = con + "px";
      }
    })
    return this;
  } else {
    // return this.eles[0].style.height;
    // return parseInt(getStyle(this.eles[0], "height"));
    return parseInt(this.getStyle("height"));
  }
}

GetEle.prototype.getStyle = function (attr) {
  var ele = this.eles[0]; //默认获取集合中的第一个
  if (window.getComputedStyle) {
    return window.getComputedStyle(ele)[attr];
  } else {
    return ele.currentStyle[attr];
  }
}

// attr()   获取和设置标签内的属性(属性节点)
// attr(key,val) 两个参数    setAttribute()
// attr(key)     一个参数    getAttribute()

GetEle.prototype.attr = function (key, val) {
  if (arguments.length >= 2) {
    this.each(function (ele) {
      ele.setAttribute(key, val);
    })
    return this;
  } else if (arguments.length == 1) {
    return this.eles[0].getAttribute(key);
  } else {
    var err = new SyntaxError("place entry at last one paramter!");
    throw err;
  }
}


// prop()   获取和设置元素节点的属性
// prop(key,val)  两个参数    ele.className = "a"
// prop(key)      一个参数    ele.className

GetEle.prototype.prop = function (key, val) {
  if (arguments.length >= 2) {   // 两个参数
    this.each(function (ele) {
      ele[key] = val;
    })
    return this;
  } else if (arguments.length == 1) {  //  一个参数
    return this.eles[0][key];
  } else {
    var err = new SyntaxError("pleace entry at least one paramter!");
    throw err;
  }
}

// css()   获取和设置元素的样式
// css("background","red")   两个参数 设置样式
// css("background")         一个参数 获取样式

GetEle.prototype.css = function (key, val) {
  if (arguments.length >= 2) {   // 两个参数
    this.each(function (ele) {
      ele.style[key] = val;
    })
    return this;
  } else if (arguments.length == 1) {
    //  一个参数  (a.如果参数是一个对象 遍历获取键值对 => 设置   b.是字符串 => 获取)
    if (typeof arguments[0] == "object") {
      for (var k in arguments[0]) {
        var v = arguments[0][k];
        this.css(k, v);
      }
      return this;
    } else if (typeof arguments[0] == "string") {
      return this.getStyle(key);
    }
  } else {
    var err = new SyntaxError("pleace entry at least one paramter!");
    throw err;
  }
}

// addClass()   向匹配的元素中添加一个或多个class名  多个class名空格分隔
GetEle.prototype.addClass = function (con) {
  var list = con.split(" ");
  this.each(function (ele) {
    ele.classList.add(...list);
  })
  return this;
}

// removeClass()   向匹配的元素中添加一个或多个class名  多个class名空格分隔
GetEle.prototype.removeClass = function (con) {
  var list = con.split(" ");
  this.each(function (ele) {
    ele.classList.remove(...list);
  })
  return this;
}

// eq(index)    返回对应下标元素形成的实例化对象  => 对应下标取值

// $(".list li").eq(0).css()  => eq() 方法返回的也是一个实例化对象
// {eles:[li,li,li,li,li,li]}   =>  {eles:[li]} 

GetEle.prototype.eq = function (index) {
  var ele = this.eles[index];  //取对应下标的元素
  this.eles = [ele];    // 将原本的实例化对象的集合  替换为新的 集合
  return this;   //{eles:[li]}    返回对应下标元素形成的实例化对象
}

// siblings()   返回 除被选中元素之外 所有的同级元素形成的实例化对象
// $(".list li").eq(0).siblings().css()  // 同级元素中 除第一个以外的 其他所有同级元素

GetEle.prototype.siblings = function () {
  var ele = this.eles[0];  //被选中的元素
  var parentEle = ele.parentElement;
  var children = parentEle.children;
  //    同级元素中  除被选中的元素以外的  其他所有同级元素
  var list = Array.from(children).filter(item => item !== ele);
  this.eles = list;   // 将原本的实例化对象的集合  替换为新的 集合
  return this;  //{ele:[li,li,li,li,li]}
}

// 对 构造函数GetEle进行二次封装  可以根据传入的选择器 快速得到对应的实例化对象
function $ (selector) {
  return new GetEle(selector);  // {eles:[]}
}


